﻿// =====================================================================
// <copyright file="ReflectionHelper.cs" author="David R. Guindo">
// 	Copyright (C) 2013. All rights reserved.
// </copyright>
// =====================================================================
// This code is released under the terms of the Apache 2.0 license, 
// http://apache.org/licenses/LICENSE-2.0.html
// =====================================================================

namespace AppBlock.Core
{
    using System;
    using System.Linq.Expressions;
    using System.Reflection;
    using Newtonsoft.Json;

    /// <summary>
    ///     TODO: Update summary.
    /// </summary>
    public static class ReflectionHelper
    {
        /// <summary>
        ///     Method to get the name of the entity
        /// </summary>
        /// <param name="name"> Name. </param>
        /// <returns> Name of the Entity </returns>
        public static string FilterProxyName(string name)
        {
            int pos = name.LastIndexOf("_", StringComparison.Ordinal);

            if (pos == -1)
            {
                return name;
            }

            return name.Substring(0, name.LastIndexOf("_", StringComparison.Ordinal));
        }

        public static object CallGenericStaticClassMethod(
            Type genericClass
            , Type genericType
            , string methodName
            , params object[] args)
        {
            return genericClass.MakeGenericType(genericType).InvokeMember(
                methodName
                , BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod
                , null
                , null
                , args);
        }

        public static TTarget Map<TSource, TTarget>(TSource source) where TTarget : class
        {
            string serialized = JsonConvert.SerializeObject(source, Formatting.Indented,
                new JsonSerializerSettings {ReferenceLoopHandling = ReferenceLoopHandling.Ignore});
            return JsonConvert.DeserializeObject<TTarget>(serialized);
        }


        /// <summary>
        ///     Properties the name.
        /// </summary>
        /// <param name="property"> The property. </param>
        /// <returns> </returns>
        public static string PropertyName(LambdaExpression property)
        {
            LambdaExpression lambda = property;

            MemberExpression memberExpression;
            if (lambda.Body is UnaryExpression)
            {
                var unaryExpression = (UnaryExpression) lambda.Body;
                memberExpression = (MemberExpression) unaryExpression.Operand;
            }
            else
            {
                memberExpression = (MemberExpression) lambda.Body;
            }

            return memberExpression.Member.Name;
        }

        public static string GetPropertyName<TProperty>(Expression<Func<TProperty>> propertyLambda)
        {
            return GetPropertyInfo(propertyLambda).Name;
        }

        public static PropertyInfo GetPropertyInfo<TProperty>(Expression<Func<TProperty>> propertyLambda)
        {
            MemberExpression member = propertyLambda.Body as MemberExpression;
            if (member == null)
                throw new ArgumentException(string.Format(
                    "Expression '{0}' refers to a method, not a property.",
                    propertyLambda.ToString()));

            PropertyInfo propInfo = member.Member as PropertyInfo;
            if (propInfo == null)
                throw new ArgumentException(string.Format(
                    "Expression '{0}' refers to a field, not a property.",
                    propertyLambda.ToString()));

            return propInfo;
        }
    }
}